/*
 * Wazuh Vulnerability scanner - Scan Orchestrator
 * Copyright (C) 2015, Wazuh Inc.
 * May 14, 2024.
 *
 * This program is free software; you can redistribute it
 * and/or modify it under the terms of the GNU General Public
 * License (version 2) as published by the FSF - Free Software
 * Foundation.
 */

#ifndef _ARRAY_RESULT_INDEXER_HPP
#define _ARRAY_RESULT_INDEXER_HPP

#include "chainOfResponsability.hpp"
#include "indexerConnector.hpp"
#include "scanContext.hpp"

/**
 * @brief ArrayResultIndexer class.
 *
 * @tparam TIndexerConnector indexer connector type.
 * @tparam TScanContext scan context type.
 */
template<typename TIndexerConnector = IndexerConnector, typename TScanContext = ScanContext>
class TArrayResultIndexer final : public AbstractHandler<std::shared_ptr<TScanContext>>
{
private:
    std::shared_ptr<TIndexerConnector> m_indexerConnector;

public:
    // LCOV_EXCL_START
    /**
     * @brief ArrayResultIndexer constructor.
     *
     * @param indexerConnector Indexer connector.
     */
    explicit TArrayResultIndexer(std::shared_ptr<TIndexerConnector> indexerConnector)
        : m_indexerConnector(std::move(indexerConnector))
    {
    }
    // LCOV_EXCL_STOP

    /**
     * @brief Handles request and passes control to the next step of the chain.
     *
     * @param data Scan context.
     * @return std::shared_ptr<TScanContext> Abstract handler.
     */
    std::shared_ptr<TScanContext> handleRequest(std::shared_ptr<TScanContext> data) override
    {
        auto resultCallback = [&](const nlohmann::json& result, const std::string& key)
        {
            logDebug2(WM_VULNSCAN_LOGTAG, "Processing and publish key: %s", key.c_str());
            if (result.contains("operation") && result.contains("id"))
            {
                m_indexerConnector->publish(result.dump());
            }
            else
            {
                logError(WM_VULNSCAN_LOGTAG,
                         "Invalid element to publish (no operation or id fields): %s.",
                         result.dump().c_str());
            }
        };

        for (const auto& [key, value] : data->m_elements)
        {
            if (!value.is_array())
            {
                throw std::invalid_argument("Invalid element to publish (not an array): " + value.dump());
            }

            for (const auto& element : value)
            {
                resultCallback(element, key);
            }
        }

        return AbstractHandler<std::shared_ptr<TScanContext>>::handleRequest(std::move(data));
    }
};

using ArrayResultIndexer = TArrayResultIndexer<>;

#endif // _ARRAY_RESULT_INDEXER_HPP
